package cc.rengu.igas.opms.core.service.trans.common;

import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.ManageService;
import cc.rengu.igas.opms.facade.request.ModifyLimitAmtRequest;
import cc.rengu.igas.opms.facade.response.ModifyLimitAmtResponse;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.SignAcctInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.LimitAcctTypeEnum;
import cc.rengu.oltp.service.common.enums.LimitTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.TransLimitInfo;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;

/**
 * 修改支付限额服务
 * 以用户作为维度进行修改(限额限次表)
 * 当前交易区分获取用户/机构的限额信息和修改用户的限额信息
 *
 * @author keyi
 * @modify by wangcheng
 * @date 2020/4/3.
 */
public class ModifyLimitAmtService extends ManageService {
    @Override
    protected Object bizBeforeCust() throws Exception {
        ModifyLimitAmtRequest modifyLimitAmtRequest = new ModifyLimitAmtRequest();
        ConvertUtil.convertOutput(modifyLimitAmtRequest);
        String bizType = modifyLimitAmtRequest.getHeader().getBizType();
        //校验设置限额的交易必输字段
        if ("01".equals(bizType) || "02".equals(bizType)){
            if (StringUtil.isEmptyOrNull(modifyLimitAmtRequest.getPassword())) {
                rglog.info("设置用户限额的交易未上传支付密码:<{}>", modifyLimitAmtRequest.getPassword());
                throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
            }else if (StringUtil.isEmptyOrNull(modifyLimitAmtRequest.getDayLimitAmt())) {
                rglog.info("设置用户限额的交易未上传单日限额:<{}>", modifyLimitAmtRequest.getDayLimitAmt());
                throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
            } else if (StringUtil.isEmptyOrNull(modifyLimitAmtRequest.getSingleLimitAmt())) {
                rglog.info("设置用户限额的交易未上传单笔限额:<{}>", modifyLimitAmtRequest.getSingleLimitAmt());
                throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
            }
            if ("02".equals(bizType)) {
                if (StringUtil.isEmptyOrNull(modifyLimitAmtRequest.getSignTokenType()) ||
                        StringUtil.isEmptyOrNull(modifyLimitAmtRequest.getSignTokenType()) ||
                        StringUtil.isEmptyOrNull(modifyLimitAmtRequest.getPayAcctNo())) {
                    rglog.error("修改用户签约账户限额，未上送签约token及签约账号信息!");
                    throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
                }
            }
        }

        return modifyLimitAmtRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {

        ModifyLimitAmtRequest modifyLimitAmtRequest = (ModifyLimitAmtRequest) request;
        ModifyLimitAmtResponse modifyLimitAmtResponse = new ModifyLimitAmtResponse();
        String bizType = modifyLimitAmtRequest.getHeader().getBizType();
        String instId = modifyLimitAmtRequest.getHeader().getInstId();
        String userId = modifyLimitAmtRequest.getUserId();
        String singleLimitAmt = modifyLimitAmtRequest.getSingleLimitAmt();
        String dayLimitAmt = modifyLimitAmtRequest.getDayLimitAmt();
        //校验单日限额必须大于等于单笔限额
        if (AmountUtil.compare(dayLimitAmt, singleLimitAmt) == -1) {
            rglog.info("用户设置的单日限额:<{}>小于单笔限额:<{}>", dayLimitAmt, singleLimitAmt);
            throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
        }

        //检查会话
        UserService userService = new UserServiceImpl();
        UserInfo userInfo = userService.getUserInfo(instId, userId, modifyLimitAmtRequest.getHeader().getSession());
        if (null == userInfo) {
            rglog.error("获取用户信息失败!");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        String userInst = userInfo.getUserInst();

        //用户验证 支付密码校验
        if ("01".equals(bizType) || "02".equals(bizType)) {
            boolean checkResult = userService.checkUserPayPassword(instId, modifyLimitAmtRequest.getUserId(), null, modifyLimitAmtRequest.getPassword());
            if (!checkResult) {
                rglog.error("用户密码错误!");
                throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
            }
        }

        /*
         * 以报文体中的transType区分是获取限额信息还是修改用户的限额
         * 若获取限额信息，先查询用户的限额，当用户限额不存在时再按机构的维度返回限额数据
         */
        rglog.debug("正在修改{}信息！", "00".equals(bizType) ? "用户收银台限额" : "用户签约账号限额");
        if ("00".equals(bizType)){
            /* 先获取用户限额 */
            TransLimitInfo transLimitInfo = userService.getUserLimitCfgInfo(instId,userId,userInst,LimitTypeEnum.CASHIER.getLimitType());
            if (null == transLimitInfo) {
                //获取机构的限额信息
                transLimitInfo = userService.getUserLimitCfgInfo(instId, instId, userInst, LimitTypeEnum.CASHIER.getLimitType());
                if (null == transLimitInfo) {
                    rglog.warn("未设置机构默认的收银台限额信息,userId：<{}>", userId);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }
            }
            modifyLimitAmtRequest.setDayLimitAmt(transLimitInfo.getDayLimitAmt());
            modifyLimitAmtRequest.setSingleLimitAmt(transLimitInfo.getSingleLimitMaxAmt());
        } else if ("01".equals(bizType)) {
            //获取机构的限额信息
            TransLimitInfo transLimitInfo = userService.getUserLimitCfgInfo(instId, instId, userInst, LimitTypeEnum.CASHIER.getLimitType());
            if (null == transLimitInfo) {
                rglog.warn("未设置机构默认的收银台限额信息,userId：<{}>", userId);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            //设置的单笔限额不能大于机构默认的单笔最大限额
            if (null == transLimitInfo.getSingleLimitMaxAmt()) {
                rglog.info("机构单笔限额金额未配置，instId:<{}>", instId);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            if (AmountUtil.compare(singleLimitAmt, transLimitInfo.getSingleLimitMaxAmt()) == OpmsParamConstant.INT_ONE) {
                rglog.info("用户设置的单笔限额设置超过机构默认单笔限额，bankDefaultSingleLimitAmt:<{}>", transLimitInfo.getSingleLimitMaxAmt());
                throw new BizException(RespCodeEnum.OVER_DEFAULT_LIMIT_AMT.getRespCode(), RespCodeEnum.OVER_DEFAULT_LIMIT_AMT.getRespDesc());
            }
            //设置的单日限额不能大于机构默认的单日限额
            if (null == transLimitInfo.getDayLimitAmt()) {
                rglog.info("机构单日限额金额未配置，instId:<{}>", instId);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            if (AmountUtil.compare(dayLimitAmt, transLimitInfo.getDayLimitAmt()) == OpmsParamConstant.INT_ONE) {
                rglog.info("用户设置的单日限额设置超过机构默认单日限额，bankDefaultDayLimitAmt:<{}>", transLimitInfo.getDayLimitAmt());
                throw new BizException(RespCodeEnum.OVER_DEFAULT_LIMIT_AMT.getRespCode(), RespCodeEnum.OVER_DEFAULT_LIMIT_AMT.getRespDesc());
            }
            //修改支付限额
            updateUserLimitInfo(modifyLimitAmtRequest, userInst);
            //设置返回信息
            modifyLimitAmtResponse.setDayLimitAmt(transLimitInfo.getDayLimitAmt());
            modifyLimitAmtResponse.setSingleLimitAmt(transLimitInfo.getSingleLimitMaxAmt());
        } else {
            SysParamService sysParamService = new SysParamServiceImpl();
            SysParam singleSysParam = sysParamService.getSysParamInfo(instId, OpmsParamConstant.OPMS_PARAM_TYPE, OpmsParamConstant.SINGLE_LIMIT_AMT);
            SysParam daySysParam = sysParamService.getSysParamInfo(instId, OpmsParamConstant.OPMS_PARAM_TYPE, OpmsParamConstant.DAY_LIMIT_AMT);
            //设置的单笔限额不能大于机构默认的单笔最大限额
            if (null == singleSysParam) {
                rglog.info("机构单笔限额金额未配置，instId:<{}>", instId);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            if (AmountUtil.compare(singleLimitAmt, singleSysParam.getParamValue()) == OpmsParamConstant.INT_ONE) {
                rglog.info("用户设置的单笔限额:<{}>超过机构默认单笔限额:<{}>", singleLimitAmt, singleSysParam.getParamValue());
                throw new BizException(RespCodeEnum.OVER_DEFAULT_LIMIT_AMT.getRespCode(), RespCodeEnum.OVER_DEFAULT_LIMIT_AMT.getRespDesc());
            }
            //设置的单日限额不能大于机构默认的单日限额
            if (null == daySysParam) {
                rglog.info("机构单日限额金额未配置，instId:<{}>", instId);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            if (AmountUtil.compare(dayLimitAmt, daySysParam.getParamValue()) == OpmsParamConstant.INT_ONE) {
                rglog.info("用户设置的单日限额:<{}>超过机构默认单日限额:<{}>", dayLimitAmt, daySysParam.getParamValue());
                throw new BizException(RespCodeEnum.OVER_DEFAULT_LIMIT_AMT.getRespCode(), RespCodeEnum.OVER_DEFAULT_LIMIT_AMT.getRespDesc());
            }
            //获取签约账号的签约信息
            String signToken = modifyLimitAmtRequest.getSignToken();
            String signTokenType = modifyLimitAmtRequest.getSignTokenType();
            String signInst = userService.getUserSignInst();
            SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
            SignAcctInfo signAcctInfo = signAcctInfoMapper.selectSignAcctInfoByPrimaryKey(instId, signTokenType, signToken, signInst);
            if (null == signAcctInfo || signAcctInfo.getSignAcctNo().endsWith(modifyLimitAmtRequest.getPayAcctNo())) {
                rglog.warn("用户未签约或者上送的签约账号与实际签约账号不匹配！");
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            signAcctInfo.setSingleLimitAmt(singleLimitAmt);
            signAcctInfo.setDayLimitAmt(dayLimitAmt);
            int iReturnCode = signAcctInfoMapper.updateSignAcctInfoByPrimaryKey(signAcctInfo);
            if (0 != iReturnCode) {
                rglog.error("更新签约账号<{}>的限额信息失败！", modifyLimitAmtRequest.getPayAcctNo());
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        }
        //返回响应信息
        modifyLimitAmtResponse.setDayLimitAmt(modifyLimitAmtRequest.getDayLimitAmt());
        modifyLimitAmtResponse.setSingleLimitAmt(modifyLimitAmtRequest.getSingleLimitAmt());
        BizResponse<ModifyLimitAmtResponse> bizResponse = new BizResponse<>();
        bizResponse.setResult(modifyLimitAmtResponse);
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        ModifyLimitAmtResponse modifyLimitAmtResponse = (ModifyLimitAmtResponse) bizResponse.getResult();
        ConvertUtil.convertInput(modifyLimitAmtResponse);
    }

    /**
     * 插入或更新用户限额限次数据信息
     *
     * @param modifyLimitAmtRequest 请求
     * @param userInst              用户所属主体
     * @throws Exception 异常
     */
    private void updateUserLimitInfo(ModifyLimitAmtRequest modifyLimitAmtRequest, String userInst) throws Exception {
        //获取用户的限额信息
        UserService userService = new UserServiceImpl();
        TransLimitInfo transLimitInfo = userService.getUserLimitCfgInfo(modifyLimitAmtRequest.getHeader().getInstId(), modifyLimitAmtRequest.getUserId(), userInst, LimitTypeEnum.CASHIER.getLimitType());
        if (null == transLimitInfo) {
            rglog.info("用户还未设置收银台限额信息,设置用户限额,userId：<{}>,", modifyLimitAmtRequest.getUserId());
            transLimitInfo = new TransLimitInfo();
            transLimitInfo.setInstId(modifyLimitAmtRequest.getHeader().getInstId());
            transLimitInfo.setLimitType(LimitTypeEnum.CASHIER.getLimitType());
            transLimitInfo.setLimitInst(userInst + "|" + modifyLimitAmtRequest.getUserId());
            transLimitInfo.setLimitAcctType(LimitAcctTypeEnum.ALL.getAcctType());
            transLimitInfo.setSingleLimitMaxAmt(modifyLimitAmtRequest.getSingleLimitAmt());
            transLimitInfo.setDayLimitAmt(modifyLimitAmtRequest.getDayLimitAmt());
            boolean updateFlag = userService.registerUserLimitInfo(transLimitInfo);
            //判断数据库操作结果
            if (!updateFlag) {
                rglog.error("登记用户限额信息失败！");
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        } else {
            rglog.info("用户:<{}>在当前用户主体:<{}>上已存在设置限额信息，更新原数据", modifyLimitAmtRequest.getUserId(), userInst);
            transLimitInfo.setSingleLimitMaxAmt(modifyLimitAmtRequest.getSingleLimitAmt());
            transLimitInfo.setDayLimitAmt(modifyLimitAmtRequest.getDayLimitAmt());
            boolean updateFlag = userService.updateUserLimitInfo(transLimitInfo);
            //判断数据库操作结果
            if (!updateFlag) {
                rglog.error("更新用户限额信息失败！");
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        }
    }
}
